﻿using System;
using System.Collections.Generic;
using System.Timers;
using CSharp.Libs.Koc.KernelModels;
using CSharp.Libs.Koc.KernelModels.ItemClasses;
using CSharp.Libs.WPF;

namespace CSharp.Libs.Koc.KernelViewModels
{
    public class InfoViewModel : ViewModelBase
    {
        #region declarations
        private Kernel _AB = null;

        private Timer _tmrAktuelleDaten = null;
        private Timer _tmrStatsTimer = null;

        private Dictionary<Int32, SeedCityItem> _dicCitiesResources = new Dictionary<int, SeedCityItem>();

        private String _strCityData = "";
        private String _strStatsTimerResult = "";
        #endregion



        #region constructor / terminator
        public InfoViewModel(
            Kernel AB)
        {
            _AB = AB;

            _AB.TM.SeedChanged += new TrafficMonitor.SeedChangedEventHandler(TM_SeedChanged);
            _AB.TM.KocServerChanged += new TrafficMonitor.KocServerChangedEventHandler(TM_KocServerChanged);

            _AB.BSVM.SeedUpdated += new BaseSeedViewModel.SeedUpdatedEventHandler(BSVM_SeedUpdated);

            _tmrAktuelleDaten = new Timer(1000);
            _tmrAktuelleDaten.Elapsed += new ElapsedEventHandler(_tmrAktuelleDaten_Elapsed);
            _tmrStatsTimer = new Timer(3600000); //Standard 1 Stunde
            _tmrStatsTimer.Elapsed += new ElapsedEventHandler(_tmrResourceStats_Elapsed);
        }

        ~InfoViewModel()
        {
            if (_tmrAktuelleDaten.Enabled)
            {
                _tmrAktuelleDaten.Stop();
            }
            _tmrAktuelleDaten.Elapsed -= _tmrAktuelleDaten_Elapsed;
            _tmrAktuelleDaten.Dispose();
            _tmrAktuelleDaten = null;

            if (_tmrStatsTimer.Enabled)
            {
                _tmrStatsTimer.Stop();
            }
            _tmrStatsTimer.Elapsed -= _tmrResourceStats_Elapsed;
            _tmrStatsTimer.Dispose();
            _tmrStatsTimer = null;

            if (_AB != null)
            {
                if (_AB.BSVM != null)
                {
                    _AB.BSVM.SeedUpdated -= BSVM_SeedUpdated;
                }

                if(_AB.TM != null)
                {
                    _AB.TM.KocServerChanged -= TM_KocServerChanged;
                    _AB.TM.SeedChanged -= TM_SeedChanged;
                }

                _AB = null;
            }
        }
        #endregion



        #region event handling
        void TM_SeedChanged(object sender)
        {
            _GetCityData();

            OnPropertyChanged("CurrentServerId");
            OnPropertyChanged("CityData");
            OnPropertyChanged("SeedCount");
        }

        void TM_KocServerChanged(object sender)
        {
            OnPropertyChanged("CurrentServerId");
            
            Int32 intCurrentServerId=0;
            if (Int32.TryParse(_AB.TM.CurrentServerId, out intCurrentServerId))
            {
                _AB.UH.SetNewServerId(intCurrentServerId);
            }
        }

        void BSVM_SeedUpdated(object sender)
        {
            try
            {
                _GetCityData();
                OnPropertyChanged("CityData");
                OnPropertyChanged("UpdateSeed_reqmicrotime");
                OnPropertyChanged("UpdateSeed_resmicrotime");
            }
            catch (Exception ex)
            {
                _AB.EC.AddException(ex, this.ToString(), _AB.EC.Tools.GetCurrentMethodName());
            }
        }

        void _tmrAktuelleDaten_Elapsed(object sender, ElapsedEventArgs e)
        {
            _GetCityData();
            OnPropertyChanged("CityData");
        }

        void _tmrResourceStats_Elapsed(object sender, ElapsedEventArgs e)
        {
            _GetResourceStats();
        }
        #endregion



        #region private functions
        /// <summary>_GetCityData</summary>
        private void _GetCityData()
        {
            try
            {
                if (_AB.TM.UserIsValid)
                {
                    String strFormat = "{0,10}  {1,-15}  {2,7}  {3,10}  {4,10}     {5,15}  {6,15}  {7,15}  {8,15}  {9,15}  {10,15}";
                    _strCityData = "";

                    _strCityData = String.Concat(
                        _strCityData,
                        String.Format(strFormat,
                            "CityID",
                            "CityName",
                            "X,Y Coords",
                            "ProvinceID",
                            "MapTileID",
                            "Food   ",
                            "Wood   ",
                            "Stone   ",
                            "Ore   ",
                            "Usage",
                            "Time left"),
                        Environment.NewLine);

                    _strCityData = String.Concat(
                        _strCityData,
                        "-----------------------------------------------------------------------------------------------------------------------------------",
                        Environment.NewLine);

                    Int64 intCurrentFood = 0;
                    Int64 intCurrentFoodUsage = 0;
                    Int32 CurrentTimestamp = _AB.conv_Date2Timestamp(DateTime.Now);

                    Int64 intSumFood = 0;
                    Int64 intSumWood = 0;
                    Int64 intSumStone = 0;
                    Int64 intSumOre = 0;
                    Int64 intSumFoodUsage = 0;

                    foreach (SeedCityItem SCI in _AB.BSVM.Cities)
                    {
                        //intCurrentFood = (Int64)_AB.GetCurrentValue(SCI.Resources.Tick, (Double)SCI.Resources.Food.Value, (Double)SCI.Resources.Food.Usage);
                        intCurrentFoodUsage = SCI.Resources.Food.Production - SCI.Resources.Food.Usage;

                        if (CurrentTimestamp > SCI.Resources.Tick)
                        {
                            Double Diff = (intCurrentFoodUsage / 3600) * (CurrentTimestamp - SCI.Resources.Tick);
                            intCurrentFood = SCI.Resources.Food.Value + (Int64)Diff;
                        }

                        intCurrentFood = (Int64)_AB.GetCurrentValue(SCI.Resources.Tick, SCI.Resources.Food);

                        _strCityData = String.Concat(
                            _strCityData,
                            String.Format(strFormat,
                                SCI.CityID,
                                SCI.CityName,
                                String.Concat(SCI.xCoord, ",", SCI.yCoord),
                                SCI.ProvinceID,
                                SCI.MapTileID,
                                intCurrentFood.ToString("0,000"),
                                SCI.Resources.Wood.Value.ToString("0,000"),
                                SCI.Resources.Stone.Value.ToString("0,000"),
                                SCI.Resources.Ore.Value.ToString("0,000"),
                                intCurrentFoodUsage.ToString("0,000"),
                                (intCurrentFood / intCurrentFoodUsage).ToString("0.000")),
                            Environment.NewLine);

                        //_strCityData = String.Concat(
                        //    _strCityData,
                        //    String.Format(strFormat,
                        //        SCI.CityID,
                        //        SCI.CityName,
                        //        String.Concat(SCI.xCoord, ",", SCI.yCoord),
                        //        SCI.ProvinceID,
                        //        SCI.MapTileID,
                        //        intCurrentFood.ToString("0,000"),
                        //        ((Int64)_AB.GetCurrentValue(SCI.Resources.Tick, (Double)SCI.Resources.Wood.Value, (Double)SCI.Resources.Wood.Usage)).ToString("0,000"),
                        //        ((Int64)_AB.GetCurrentValue(SCI.Resources.Tick, (Double)SCI.Resources.Stone.Value, (Double)SCI.Resources.Stone.Usage)).ToString("0,000"),
                        //        ((Int64)_AB.GetCurrentValue(SCI.Resources.Tick, (Double)SCI.Resources.Ore.Value, (Double)SCI.Resources.Ore.Usage)).ToString("0,000"),
                        //        intCurrentFoodUsage.ToString("0,000"),
                        //        (intCurrentFood / intCurrentFoodUsage).ToString("0.000")),
                        //    Environment.NewLine);

                        //(_AB.GetCurrentValue(SCI.Resources.Tick, (Double)SCI.Resources.Food.Value, (Double)SCI.Resources.Food.Usage) / (Double)SCI.Resources.Food.Usage).ToString("0.000")

                        intSumFood += SCI.Resources.Food.Value;
                        intSumWood += SCI.Resources.Wood.Value;
                        intSumStone += SCI.Resources.Stone.Value;
                        intSumOre += SCI.Resources.Ore.Value;
                        intSumFoodUsage += SCI.Resources.Food.Usage;
                    }

                    _strCityData = String.Concat(
                        _strCityData,
                        "-----------------------------------------------------------------------------------------------------------------------------------",
                        Environment.NewLine);

                    _strCityData = String.Concat(
                        _strCityData,
                        String.Format(strFormat,
                            "", "", "", "", 
                            "Sums:",
                            intSumFood.ToString("0,000"),
                            intSumWood.ToString("0,000"),
                            intSumStone.ToString("0,000"),
                            intSumOre.ToString("0,000"),
                            "",
                            ""));
                }
            }
            catch (Exception ex)
            {
                _AB.EC.AddException(ex, this.ToString(), _AB.EC.Tools.GetCurrentMethodName());
            }
        }

        /// <summary>_GetResourceStats</summary>
        /// <history>24.05.2011</history>
        private void _GetResourceStats()
        {
            try
            {
                if (_dicCitiesResources.Count > 0)
                {
                    String strFormat = "{0,16}    ";
                    String strCityNames =   "Names: ";
                    String strTrenner =     "-------";
                    String strFood =        "Food : ";
                    String strWood =        "Wood : ";
                    String strStone =       "Stone: ";
                    String strOre =         "Ore  : ";

                    //Calculate Diffs.
                    foreach (SeedCityItem SCI in _AB.BSVM.Cities)
                    {
                        SeedCityItem sciOld = _dicCitiesResources[SCI.CityID];//

                        strCityNames += String.Format(strFormat, SCI.CityName);
                        strTrenner += "--------------------";
                        strFood += String.Format(strFormat, (SCI.Resources.Food.Value - sciOld.Resources.Food.Value).ToString("0,000"));
                        strWood += String.Format(strFormat, (SCI.Resources.Wood.Value - sciOld.Resources.Wood.Value).ToString("0,000"));
                        strStone += String.Format(strFormat, (SCI.Resources.Stone.Value - sciOld.Resources.Stone.Value).ToString("0,000"));
                        strOre += String.Format(strFormat, (SCI.Resources.Ore.Value - sciOld.Resources.Ore.Value).ToString("0,000"));
                    }

                    _strStatsTimerResult = String.Concat(
                        strCityNames, Environment.NewLine,
                        strTrenner, Environment.NewLine,
                        strFood, Environment.NewLine,
                        strWood, Environment.NewLine,
                        strStone, Environment.NewLine,
                        strOre, Environment.NewLine,
                        "Last Update: ", DateTime.Now.ToString(constants.DATE_TIME_STAMP_MASK_LOG_ENTRY));

                    //Remove old item.
                    _dicCitiesResources.Clear();
                }

                //Add current Values
                foreach (SeedCityItem SCI in _AB.BSVM.Cities)
                {
                    SeedCityItem sciValues = new SeedCityItem();

                    sciValues.Resources.Food.Value = SCI.Resources.Food.Value;
                    sciValues.Resources.Wood.Value = SCI.Resources.Wood.Value;
                    sciValues.Resources.Stone.Value = SCI.Resources.Stone.Value;
                    sciValues.Resources.Ore.Value = SCI.Resources.Ore.Value;

                    _dicCitiesResources.Add(SCI.CityID, sciValues);
                }

                OnPropertyChanged("StatsTimerResult");
            }
            catch (Exception ex)
            {
                _AB.EC.AddException(ex, this.ToString(), _AB.EC.Tools.GetCurrentMethodName());
            }
        }
        #endregion



        #region interface
        #region properties
        public String CurrentServerId
        {
            get
            {
                return _AB.TM.CurrentServerId;
            }
        }

        public String CityData
        {
            get
            {
                return _strCityData;
            }
        }

        public Int32 SeedCount
        {
            get
            {
                return _AB.TM.SeedCount;
            }
        }

        public Boolean CityDataRefreshTimerActive
        {
            get
            {
                return _tmrAktuelleDaten.Enabled;
            }
            set
            {
                _tmrAktuelleDaten.Enabled = value;
            }
        }

        public String UpdateSeed_reqmicrotime
        {
            get
            {
                return _AB.BSVM.UpdateSeed_reqmicrotime;
            }
        }

        public String UpdateSeed_resmicrotime
        {
            get
            {
                return _AB.BSVM.UpdateSeed_reqmicrotime;
            }
        }

        public Boolean StatsTimerActive
        {
            get
            {
                return _tmrStatsTimer.Enabled;
            }
            set
            {
                if (value)
                {
                    _GetResourceStats();
                }

                _tmrStatsTimer.Enabled = value;
            }
        }

        public Double StatsTimerInterval
        {
            get
            {
                return _tmrStatsTimer.Interval / 1000;
            }
            set
            {
                //Alles zwischen 10 Sekunden und 10 Stunden
                if (value > 10 && value < 36000)
                {
                    _tmrStatsTimer.Interval = value * 1000;
                }
            }
        }

        public String StatsTimerResult
        {
            get
            {
                return _strStatsTimerResult;
            }
        }
        #endregion

        #region methods
        #endregion
        #endregion
    }
}
